TITLE 'DIGITAL CLOCK; 26 JUNE 82'
;
;DISPLAY TIME OF DAY IN LARGE NUMERALS
;
;EACH NUMERAL WILL BE IN A 7 X 7 BOX
;
	SSEG
	RS	80H
STACK_TOP:
	DB	0
;
	DSEG
	ORG	100H
ZERO	DB	' 00000 '
BOX_WIDTH	EQU	OFFSET $ - OFFSET ZERO
	DB	'0     0'
	DB	'0     0'
	DB	'0     0'
	DB	'0     0'
	DB	'0     0'
	DB	' 00000 '
BOX_HIGHTH	EQU	(OFFSET $ - OFFSET ZERO) / BOX_WIDTH
ONE	DB	'   11  '
	DB	'  111  '
	DB	' 1111  '
	DB	'   11  '
	DB	'   11  '
	DB	'   11  '
	DB	'1111111'
;
TWO	DB	' 22222 '
	DB	'2     2'
	DB	'     2 '
	DB	'    2  '
	DB	'   2   '
	DB	' 2     '
	DB	'2222222'
;
THREE	DB	' 33333 '
	DB	'3     3'
	DB	'      3'
	DB	'   3333'
	DB	'      3'
	DB	'3     3'
	DB	' 33333 '
;
FOUR	DB	'    44 '
	DB	'   4 4 '
	DB	'  4  4 '
	DB	' 4   4 '
	DB	'4444444'
	DB	'     4 '
	DB	'     4 '
;
FIVE	DB	'5555555'
	DB	'5      '
	DB	'5      '
	DB	' 55555 '
	DB	'      5'
	DB	'      5'
	DB	'5555555'
;
SIX	DB	' 66    '
	DB	'6      '
	DB	'6      '
	DB	'6666666'
	DB	'6     6'
	DB	'6     6'
	DB	'6666666'
;
SEVEN	DB	'7777777'
	DB	'     7 '
	DB	'    7  '
	DB	'    7  '
	DB	'    7  '
	DB	'    7  '
	DB	'    7  '
;
EIGHT	DB	' 88888 '
	DB	'8     8'
	DB	'8     8'
	DB	' 88888 '
	DB	'8     8'
	DB	'8     8'
	DB	' 88888 '
;
NINE	DB	' 99999 '
	DB	'9     9'
	DB	'9     9'
	DB	' 999999'
	DB	'      9'
	DB	'      9'
	DB	'  9999 '
;
NUMERAL_ADDRESS:
	DW	OFFSET ZERO
	DW	OFFSET ONE
	DW	OFFSET TWO
	DW	OFFSET THREE
	DW	OFFSET FOUR
	DW	OFFSET FIVE
	DW	OFFSET SIX
	DW	OFFSET SEVEN
	DW	OFFSET EIGHT
	DW	OFFSET NINE
;
BOX_POSITION:
	DW	7*256+12
	DW	16*256+12
	DW	29*256+12
	DW	38*256+12
	DW	51*256+12
	DW	60*256+12
;
CURRENT_TIME:
	DW	0
	DB	0
CUR_MIN	DB	0
CUR_SEC	DB	0
PREVIOUS_TIME:
	DW	0ffh
	DB	0ffh
PRE_MIN	DB	0ffh
PRE_SEC DB	0ffh
;

CLS	DB	'Z'-40H,'PRESS ANY KEY TO STOP$'
REVERSE_ATTRIB:
	DB	ESC,')$'
NORM_ATTRIB:
	DB	ESC,'($'
;
GET_DATE_TIME	EQU	155
DELAY		EQU	141
CON_STAT	EQU	11
EJECT
	CSEG
;
	MOV AX,.015H ! MOV SS,AX ! MOV SP,OFFSET STACK_TOP
	MOV DX,OFFSET CLS ! CALL P_MESSAGE
MAIN_LOOP:
	CALL	TIME_OF_DAY
	CALL	UPDATE_SCREEN
	CALL	MOVE_CURRENT_TO_PREVIOUS
	CALL	CHECK_FOR_STOP
	JMP	MAIN_LOOP
;
DELAY_IT:
	MOV DX,58 ! MOV CL,DELAY ! CALL BDOS
	RET
;
;
TIME_OF_DAY:
	MOV CL,GET_DATE_TIME ! MOV DX,OFFSET CURRENT_TIME
	JMP	BDOS
;
MOVE_CURRENT_TO_PREVIOUS:
	MOV SI,OFFSET CURRENT_TIME ! MOV DI,OFFSET PREVIOUS_TIME
	MOVSW ! MOVSW ! MOVSB
	RET
;
UPDATE_SCREEN:
	MOV CX,3 ! MOV SI,OFFSET CUR_SEC
	MOV DI,OFFSET PRE_SEC ! MOV BX,5
UPDATE_LOOP:
	MOV AL,[SI] ! MOV AH,[DI] ! CMP AL,AH
	JZ	NO_UPDATE	;DON'T CHANGE THE TIME
	PUSH CX ! PUSH SI ! PUSH DI ! PUSH BX
	PUSH AX ! AND AH,0FH ! AND AL,0FH 	;GET THE LOW BCD DIGITS
	CMP AL,AH ! JE NEXT_BCD			;IF = DON'T CHANGE
	CALL	UPDATE_NUMBER
NEXT_BCD:
	POP AX ! POP BX
	DEC BX ! PUSH BX	;POINT TO NEXT BOX ADDRESS
	AND AH,0F0H ! AND AL,0F0H
	CMP AH,AL ! JE CLEAR_STACK
	MOV CL,4 ! SHR AL,CL
	CALL	UPDATE_NUMBER
CLEAR_STACK:
	POP BX ! DEC BX
	POP DI ! DEC DI
	POP SI ! DEC SI
	POP	CX
	LOOP	UPDATE_LOOP
	RET
NO_UPDATE:
	CALL	DELAY_IT
	RET
;AT THIS TIME THERE IS NO REASON TO RETURN TO MAIN LOOP
; SO LET'S SEE WHAT HAPPENS WHEN OUR TIME SLICE IS GIVEN UP
;
;
UPDATE_NUMBER:
;AL=DECIMAL DIGIT
;BX=DIGIT POSITION (HOURS= POSITION 0 AND 1)
	XOR AH,AH ! MOV DI,OFFSET NUMERAL_ADDRESS
	SHL AX,1 ! ADD DI,AX ! MOV SI,[DI]
	SHL BX,1 ! MOV DI,OFFSET BOX_POSITION
	ADD DI,BX ! MOV AX,[DI]
	JMP	SHOW_NUMERAL
;
;
SHOW_NUMERAL:
;INPUT	AX=ROW,COL
;	SI= OFFSET OF NUMERAL
;
;PUT NUMERAL AT SPECIFIED CURSOR LOCATION
;
	MOV	CX,BOX_HIGHTH
SHOW_LOOP:
	PUSH CX ! PUSH AX ! PUSH SI
	CALL	PLACE
	POP SI ! PUSH SI
	MOV CX,BOX_WIDTH ! CALL PUT_CHARS
	POP SI ! ADD SI,BOX_WIDTH
	POP AX ! INC AL			;GO TO NEXT ROW
	POP CX
	LOOP	SHOW_LOOP
	RET
;
PUT_CHARS:
;INPUT	CX= # OF CHARS
;	SI= OFFSET OF CHARS
;
;PUT # OF CHARS POINTED TO BY SI ON SCREEN
;
	LODSB ! CMP AL,' ' ! JE BLANK_LOOP_1
NUM_LOOP_1:
	PUSH CX ! PUSH SI ! PUSH AX
	CALL 	REVERSE_ATTRIBUTE
	POP	DX
	JMP	NUM_LOOP_2
NUM_LOOP:
	LODSB ! CMP AL,' ' ! JE BLANK_LOOP_1
	PUSH CX ! PUSH SI
	MOV	DL,AL
NUM_LOOP_2:
	MOV CL,CON_OUT ! CALL BDOS
	POP SI ! POP CX
	LOOP	NUM_LOOP
	RET
BLANK_LOOP_1:
	PUSH CX ! PUSH SI ! PUSH AX
	CALL	NORM_ATTRIBUTE
	POP	DX
	JMP	BLANK_LOOP_2
BLANK_LOOP:
	LODSB ! CMP AL,' ' ! JNE NUM_LOOP_1
	PUSH CX ! PUSH SI
	MOV	DL,AL
BLANK_LOOP_2:
	MOV CL,CON_OUT ! CALL BDOS
	POP SI ! POP CX
	LOOP	BLANK_LOOP
	RET
;
REVERSE_ATTRIBUTE:
	MOV DX,OFFSET REVERSE_ATTRIB ! JMP P_MESSAGE
NORM_ATTRIBUTE:
	MOV DX,OFFSET NORM_ATTRIB ! JMP P_MESSAGE
;
CHECK_FOR_STOP:
	MOV CL,CON_STAT ! CALL BDOS
	CMP AL,0 ! JNE GOOD_BYE
	RET
GOOD_BYE:
	MOV DX,OFFSET NORM_ATTRIB ! CALL P_MESSAGE
	XOR CX,CX ! JMP BDOS
;
NOLIST
INCLUDE ROUTINES.A86
